package flex.cc.common.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author WANGCONG
 * 2021年9月6日下午9:02:56
 * @desc HttpClinet工具类
 */
public class HttpClientUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    /**
     * 默认参数设置
     * setConnectTimeout：设置连接超时时间，单位毫秒。
     * setConnectionRequestTimeout：设置从connect Manager获取Connection 超时时间，单位毫秒。
     * setSocketTimeout：请求获取数据的超时时间，单位毫秒。访问一个接口，多少时间内无法返回数据，就直接放弃此次调用。 
     */
    private static RequestConfig  requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).setConnectionRequestTimeout(10000).build();
   

    /**
     * 静态内部类---作用：单例产生类的实例
     *
     * @author Administrator
     */
    private static class LazyHolder {
        private static final HttpClientUtil INSTANCE = new HttpClientUtil();

    }

    private HttpClientUtil() {
    }

    public static HttpClientUtil getInstance() {
        return LazyHolder.INSTANCE;
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     */
    public String sendHttpPost(String httpUrl) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param params  参数(格式:key1=value1&key2=value2)
     */
    public static String sendHttpPost(String httpUrl, String params, Map<String, String> headerMap) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
            if (null != headerMap) {
                headerMap.forEach(httpPost::setHeader);
            }
        } catch (Exception e) {
        	logger.error("设置post参数异常", e);
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }
    
    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param params  参数(格式:key1=value1&key2=value2)
     */
    public static String sendHttpPostText(String httpUrl, String params, Map<String, String> headerMap) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("text/plain;charset=UTF-8");
            httpPost.setEntity(stringEntity);
            if (null != headerMap) {
                headerMap.forEach(httpPost::setHeader);
            }
        } catch (Exception e) {
        	logger.error("设置post参数异常", e);
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    public byte[] sendHttpPostByte(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPostByte(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param maps    参数
     */
    public String sendHttpPost(String httpUrl, Map<String, String> maps) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        // 创建参数队列
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : maps.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送Post请求
     *
     * @param httpPost
     * @return
     */
    private static String sendHttpPost(HttpPost httpPost) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        long execStart = System.currentTimeMillis();
        long execEnd = 0,getStart = 0,getEnd = 0;
        try {
        	logger.info("开始执行post请求,id=" + execStart);
            // 创建默认的httpClient实例
            httpClient = HttpClients.createDefault();
            httpPost.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPost);
            execEnd = System.currentTimeMillis();
            logger.info("执行post请求完成,id="+execStart+",耗时=" + (execEnd - execStart) + "ms");
            getStart = System.currentTimeMillis();
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
            getEnd = System.currentTimeMillis();
            logger.error("获取post响应完成,id="+execStart+",耗时：" + (getEnd - getStart) + "ms");
        } catch (Exception e) {
        	execEnd = System.currentTimeMillis();
			logger.error("执行post请求异常,id="+execStart+",耗时：" + (execEnd - execStart) + "ms", e);
            e.printStackTrace();
            responseContent = "{\"resultCode\":9999,\"message\":\"请求失败，" + e.getMessage() + "\"}";
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    private byte[] sendHttpPostByte(HttpPost httpPost) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        byte[] responseContent = null;
        try {
        	logger.info("开始执行post请求");
            // 创建默认的httpClient实例
            httpClient = HttpClients.createDefault();
            httpPost.setConfig(requestConfig);
            // 执行请求
            long execStart = System.currentTimeMillis();
            response = httpClient.execute(httpPost);
            long execEnd = System.currentTimeMillis();
            logger.info("执行post请求耗时：" + (execEnd - execStart) + "ms");
            long getStart = System.currentTimeMillis();
            entity = response.getEntity();
            responseContent = EntityUtils.toByteArray(entity);
            long getEnd = System.currentTimeMillis();
            logger.info("获取响应结果耗时：" + (getEnd - getStart) + "ms");
        } catch (Exception e) {
        	logger.error("执行post请求异常", e);
            e.printStackTrace();
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }


    /**
     * 发送 get请求
     *
     * @param httpUrl
     */
    public String sendHttpGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpGet(httpGet);
    }

    /**
     * 发送 get请求Https
     *
     * @param httpUrl
     */
    public String sendHttpsGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpsGet(httpGet);
    }

    /**
     * 发送Get请求
     * @param httpGet
     * @return
     */
    private String sendHttpGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
        	logger.info("开始发送get请求");
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();

            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
            logger.info("发送get请求完成");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("发送get请求异常", e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 发送Get请求Https
     * @param httpGet
     * @return
     */
    private String sendHttpsGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
        	logger.info("开始发送get请求");
            // 创建默认的httpClient实例.
            PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString()));
            DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
            httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
            logger.info("发送get请求完成");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("发送Get请求异常", e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }


    public static String getCodeResult(String url,String data){
    	BufferedReader b = null;
    	String result = null;
    	try {
	    	Runtime r = Runtime.getRuntime();
	    	
	    	logger.info("curl -d " + data + " " + url);
	    	String[] ml = new String[] {"curl", "-d", data, url};
	    	Process p = r.exec(ml);
	    	p.waitFor();
	    	b = new BufferedReader(new InputStreamReader(p.getInputStream()));
	    	String line = "";
	    	StringBuffer sb=new StringBuffer();
	    	while ((line = b.readLine()) != null) {
	    		sb.append(line).append("\n");
	    	}
	    	System.out.println("result： "+sb.toString());
	    	result = sb.toString();
    	}catch(Exception e) {
    		e.printStackTrace();
    	} finally {
            try {
                // 关闭连接,释放资源
                if (b != null) {
                	b.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    	return result;
    }
}
